<?php

namespace app\admin\command;

use Carbon\Carbon;
use fast\Random;
use think\console\Command;
use think\console\Input;
use think\console\input\Option;
use think\console\Output;
use think\Db;
use think\Env;
use think\Exception;
use think\Log;
use app\admin\model\pt\DutyList as DutyModel;
use app\admin\model\pt\Person as PersonModel;
use app\admin\model\pt\Depart as DepartModel;
use app\admin\model\pt\Job as JobModel;
use app\admin\model\pt\Salary as SalaryModel;
use app\common\library\Salary as SalaryLib;

class UpdatePersonJob extends Command
{

    protected $_jobModel = null;
    protected $_departModel = null;
    protected $_personModel = null;
    protected $_salaryModel = null;

    protected function configure()
    {
        $this->setName('updatepersonjob')
            ->addOption('date', 'd', Option::VALUE_OPTIONAL, 'date', date('Ymd'))
            ->setDescription('update person today job 零点后运行');
    }
    
    // 每日零点后运行，更新所有人员的当天所属工作
    // 同时也检查已安排工作的人员的状态，如果状态是隐藏工作会被删除
    protected function execute(Input $input, Output $output)
    {
        @ini_set("memory_limit",'-1');
        $stime=microtime(true);

        $curDate = $input->getOption('date');
        
        $this->_jobModel = new JobModel();
        $this->_departModel = new DepartModel();
        $this->_personModel = new PersonModel();
        $this->_salaryModel = new SalaryModel();

        $this->personInfo = null;
        $this->departInfo = null;
        $this->jobInfo = null;

        // 从人员安排表中找出对应日期有工作的人员
        $dutys = DutyModel::where('date_id', $curDate)->select();
        Log::write('update person job: 人员信息更新开始, date =>' . $curDate);
        $salaryLib = new SalaryLib();
        foreach ($dutys as $d) {
            Db::startTrans();
            try {
                // 检查岗位状态和部门状态
                $checkRes = $this->checkDuty($d);
                if ($checkRes == false) {
                    // 删除人员信息表的当前岗位信息
                    if ($this->personInfo) {
                        $this->personInfo->pt_depart_id = 0;
                        $this->personInfo->pt_job_id = 0;
                        $this->personInfo->job_date = null;
                        // 也删除薪水记录
                        $salaryLib->delSalary($this->personInfo->id, $d->date_id, $d->pt_job_id);
                    }
                    // 删除已安排的工作记录
                    $d->delete();
                } else {
                    // 更新工作到人员信息的当前岗位信息
                    $this->personInfo->pt_depart_id = $d->pt_depart_id;
                    $this->personInfo->pt_job_id = $d->pt_job_id;
                    $this->personInfo->job_date = date('Y-m-d', strtotime($curDate));
                    // 将工作内容也写入到薪酬基础表
                    $salaryLib->setObject($this->personInfo, $this->departInfo, $this->jobInfo);
                    $salaryLib->addSalary($d->id, $curDate);
                }
                $this->personInfo->save();
                Log::write('update person job: 人员信息更新完成, id =>' . $d->pt_person_id);
                Db::commit();
            } catch (Exception $e) {
                Db::rollback();
                print_r($e->getTraceAsString());
                Log::write('update person job: 人员信息失败, message:'.$e->getMessage() .', duty id =>' . $d->id);
            }
            
        }
        // 对应日期无工作安排的,将人员信息表的信息清除
        $persons = PersonModel::where('job_date', '<>', date('Y-m-d', strtotime($curDate)))->select();
        foreach ($persons as $person) {
            $person->pt_depart_id = 0;
            $person->pt_job_id = 0;
            $person->job_date = null;
            $person->save();
        }
        Log::write('update person job: 人员信息更新结束, date =>' . $curDate);


        $etime=microtime(true);//获取程序执行结束的时间
        $total=$etime-$stime;   //计算差值
        $output->writeln($total);
        $output->info('update person job success');
    }

    private function checkDuty($dutyInfo)
    {
        $personId = $dutyInfo->pt_person_id;
        $this->personInfo = $this->_personModel->get($personId);
        if (!$this->personInfo) {
            Log::write('update person job: 人员信息未找到, id =>' . $personId);
            return false;
        }
        if ($this->personInfo->status == 'hidden') {
            Log::write('update person job: 人员状态隐藏, id =>' . $personId . ', status =>' . $this->personInfo->status);
            return false;
        }
        $jobId = $dutyInfo->pt_job_id;
        $this->jobInfo = $this->_jobModel->where('id', $jobId)->find();
        if (!$this->jobInfo) {
            Log::write('岗位信息未找到, id =>' . $jobId);
            return false;
        }
        if ($this->jobInfo->status != 'normal') {
            Log::write('岗位信息已隐藏, id =>' . $jobId . ', status =>' . $this->jobInfo->status);
            return false;
        }
        $departId = $dutyInfo->pt_depart_id;
        $this->departInfo = $this->_departModel->where('id', $departId)->find();
        if (!$this->departInfo) {
            Log::write('部门信息未找到, id =>' . $departId);
            return false;
        }
        if ($this->departInfo->status != 'normal') {
            Log::write('部门信息已隐藏, id =>' . $departId . ', status =>' . $this->departInfo->status);
            return false;
        }

        return true;
    }

    private function addSalary($dutyId, $dateId)
    {
        $params = [];
        $params['duty_id'] = $dutyId;
        $params['date_id'] = $dateId;
        $params['user_id'] = $this->personInfo->user_id;
        $params['pt_person_id'] = $this->personInfo->id;
        $params['pt_depart_id'] = $this->departInfo->id;
        $params['depart_name'] = $this->departInfo->name;
        $params['pt_job_id'] = $this->jobInfo->id;
        $params['job_name'] = $this->jobInfo->name;
        $params['salary_mode'] = $this->jobInfo->salary_mode;
        $params['max_start'] = $this->jobInfo->max_start;
        // 根据人员和岗位对比后填入
        $salaryInfo = $this->checkSalary();
        if (empty($salaryInfo['salary']) && empty($salaryInfo['salary_rule'])) {
            Log::write('没有获取到薪水规则信息, job  =>' . var_export($this->jobInfo->toArray(), true));
            return ;
        }
        $params['salary_rule'] = $salaryInfo['salary_rule'];
        $params['salary'] = $salaryInfo['salary'];

        // 餐费这里先快照进来，然后每天计算薪酬的脚本根据时长判断是否改为0
        $params['added1_fee'] = $this->jobInfo->added1_fee;
        $params['added2_fee'] = $this->jobInfo->added2_fee;
        $params['require_duration'] = $this->jobInfo->attendance_duration;
        $params['require_calc_duration'] = $this->jobInfo->calc_duration;
        $salaryInfo = $this->_salaryModel->where('pt_person_id', $this->personInfo->id)
                                         ->where('date_id', $dateId)
                                         ->find();
        if ($salaryInfo) {
            $params['id'] = $salaryInfo->id;
        } else {
            $salaryInfo = new SalaryModel();
        }

        $salaryInfo->save($params);
    }

    private function checkSalary()
    {
        $salaryInfo = [
            'salary'  => 0, 
            'salary_rule' => '',
        ];
        // 获取人员类别
        $personType = $this->personInfo->user_type; 
        $laborId = $this->personInfo->pt_labor_id;
        // 劳务公司
        if ($personType == 'labor') {
            // 判断劳务公司
            $jobInfo = $this->jobInfo->toArray();
            // 判断薪资模式
            switch($jobInfo['salary_mode']) {
                case 'hour':
                  $salaryInfo['salary'] = $jobInfo['labor' . $laborId . '_salary'];
                  break;
                case 'day':
                  $salaryInfo['salary'] = $jobInfo['labor' . $laborId . '_salary_day'];
                  break;
                case 'stage':
                  $salaryInfo['salary_rule'] = $jobInfo['labor' . $laborId .'_salary_stage'];
                  break;
            }
        } else {
            // 其他都算自招 根据薪资模式取值
            switch($this->jobInfo->salary_mode) {
                case 'hour':
                  $salaryInfo['salary'] = $this->jobInfo->self_salary;
                  break;
                case 'day':
                  $salaryInfo['salary'] = $this->jobInfo->self_salary_day;
                  break;
                case 'stage':
                  $salaryInfo['salary'] = $this->jobInfo->self_salary_stage;
                  break;
            }
        }

        return $salaryInfo;
    }

}
